/*
 * cm_mib_id.h
 *
 *  Created on: 2014年9月23日
 *      Author: chens
 */

#ifndef CM_MIB_ID_H_
#define CM_MIB_ID_H_

#include <stdio.h>
#include <string.h>
#include <assert.h>
/*
 * mib id level
 * |--8bit--|--8bit--|--8bit--|--8bit--|
 *    level0	L1	L2	 L3
 */

#define CMMIB_MAX_LEVEL		(4)
#define CMMIB_MAX_ID_LEN	(128)

/*
 * @brief	节点之间关系的名称以及其枚举定义
 */
static const char *cmmib_relation_name[] = { "error", "ancestor", "parent",
		"brother branch", "child", "heir", "same" };

enum cmmib_relation {
	CMMIB_ERROR, /* level0 = 0*/
	CMMIB_ANCESTOR, /* */
	CMMIB_PARENT, /* */
	CMMIB_BROTHER, CMMIB_CHILD, CMMIB_HEIR, CMMIB_SAME
};

typedef union {
	unsigned char level[CMMIB_MAX_LEVEL];
} cmmib_id;

static const cmmib_id cmmib_error = { { 0 } };

/*
 * @brief	获取ID是属于第几层
 * @return	<0 表示ID无效
 */
static inline int cmmib_level(cmmib_id id)
{
	int i;
	for (i = 0; i < CMMIB_MAX_LEVEL; i++) {
		if (id.level[i] == 0)
			break;
	}
	return (i - 1);
}

/*
 * @brief	将形如 "1.2.3.4"的字符串转化成 ID
 * @param	str: 字符串表示的MIB， sp: 在字符串中数值的分割符
 */
static inline cmmib_id cmmib_str2id(const char *str, char sp)
{
	if (strlen(str) > CMMIB_MAX_ID_LEN)
		return cmmib_error;

	cmmib_id id;
	memset(id.level, 0, sizeof(id.level));

	char temp[CMMIB_MAX_ID_LEN];

	/* "1.12.123.4" */
	int i_begin = 0, i_end;
	int i;
	for (i = 0; i < CMMIB_MAX_LEVEL; i++) {
		i_end = strlen(str);
		snprintf(temp, i_end - i_begin + 1, "%s", str + i_begin);
		char *ptr = NULL;
		ptr = strchr(temp, sp);
		if (ptr == NULL) {
			id.level[i] = (unsigned char) atoi(temp);
			break;
		} else {
			i_end = (ptr - temp);
			temp[i_end] = 0;
			id.level[i] = (unsigned char) atoi(temp);
			i_begin += i_end + 1;
		}
	}
	return id;
}

/*
 * @brief	将ID转换成字符串形式
 */
static inline void cmmib_id2str(cmmib_id id, char *result)
{
	if (id.level[0] == 0) {
		sprintf(result, "error address.");
		return;
	}
	char temp[32];
	*result = 0;
	int i;
	for (i = 0; i < CMMIB_MAX_LEVEL; i++) {
		if (id.level[i] == 0)
			break;
		sprintf(temp, "%d.", id.level[i]);
		strcat(result, temp);
	}
	*(result + strlen(result) - 1) = 0;
}

/*
 * @brief	从数值上比较两个id
 * @return	 0: equal to
 * 		>0: greater than
 * 		<0: less than
 */
static inline int cmmib_cmp(cmmib_id id, cmmib_id cmp_to)
{
	int i;
	for (i = 0; i < CMMIB_MAX_LEVEL; i++) {
		if (id.level[i] > cmp_to.level[i])
			return 1;
		else if (id.level[i] < cmp_to.level[i])
			return -1;
	}
	return 0;
}

/*
 * @brief	获取两个节点之间的关系
 */
static inline enum cmmib_relation cmmib_relation(cmmib_id id, cmmib_id cmp_to)
{
	if (id.level[0] == 0 || cmp_to.level[0] == 0)
		return CMMIB_ERROR;

	cmmib_id ppp, ccc;
	int cmp = cmmib_cmp(id, cmp_to);
	if (cmp == 0) {
		return CMMIB_SAME;
	} else if (cmp < 0) {
		ppp = id;
		ccc = cmp_to;
	} else {
		ppp = cmp_to;
		ccc = id;
	}

	int i;
	for (i = 0; i < CMMIB_MAX_LEVEL; i++) {
		unsigned char p = ppp.level[i];
		unsigned char c = ccc.level[i];
		if (p == 0 && c == 0)
			return CMMIB_SAME;

		if (p != 0 && c != 0) {
			if (p == c)
				continue; /* same at this level */
			else
				return CMMIB_BROTHER;
		}

		if (p == 0 && c != 0) {
			if (i == (CMMIB_MAX_LEVEL - 1)
					|| ccc.level[i + 1] == 0) {
				if (cmp < 0)
					return CMMIB_PARENT;
				else
					return CMMIB_CHILD;
			} else {
				if (cmp < 0)
					return CMMIB_ANCESTOR;
				else
					return CMMIB_HEIR;
			}
		}
		return CMMIB_ERROR;
		/* p != 0 && c == 0, never get here*/
	}
	return CMMIB_ERROR;
}

#endif /* CM_MIB_ID_H_ */
